package com.hospital.service.impl;

import com.hospital.exception.FileUploadException;
import com.hospital.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 文件服务实现类
 *
 * @author Hospital Management System
 */
@Slf4j
@Service
public class FileServiceImpl implements FileService {

    @Value("${file.upload.path}")
    private String uploadPath;

    @Value("${file.upload.maxSize}")
    private long maxFileSize;

    @Value("${server.servlet.context-path:}")
    private String contextPath;

    @Value("${server.port}")
    private String serverPort;

    // 允许的图片文件类型
    private static final String[] IMAGE_TYPES = {"jpg", "jpeg", "png", "gif", "bmp", "webp"};
    
    // 允许的文档文件类型
    private static final String[] DOCUMENT_TYPES = {"pdf", "doc", "docx", "txt", "xls", "xlsx"};
    
    // 允许的所有文件类型
    private static final String[] ALL_TYPES = {"jpg", "jpeg", "png", "gif", "bmp", "webp", 
                                               "pdf", "doc", "docx", "txt", "xls", "xlsx"};

    @Override
    public String uploadFile(MultipartFile file, String type) {
        try {
            // 验证文件
            validateFile(file, type);
            
            // 创建上传目录
            String typeDir = getTypeDirectory(type);
            String dateDir = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
            Path uploadDir = Paths.get(uploadPath, typeDir, dateDir);
            
            // 确保目录存在
            Files.createDirectories(uploadDir);
            
            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String extension = getFileExtension(originalFilename);
            String newFilename = generateUniqueFilename() + "." + extension;
            
            // 保存文件
            Path filePath = uploadDir.resolve(newFilename);
            Files.copy(file.getInputStream(), filePath);
            
            // 返回访问URL（使用正斜杠，确保URL格式正确）
            String fileUrl = "/uploads/" + typeDir + "/" + dateDir + "/" + newFilename;
            fileUrl = fileUrl.replace("\\", "/");
            
            log.info("文件上传成功: {}", fileUrl);
            return fileUrl;
            
        } catch (IOException e) {
            log.error("文件上传失败", e);
            throw new FileUploadException("文件上传失败: " + e.getMessage(), e);
        }
    }

    @Override
    public List<String> uploadFiles(MultipartFile[] files, String type) {
        List<String> fileUrls = new ArrayList<>();
        
        for (MultipartFile file : files) {
            if (!file.isEmpty()) {
                String fileUrl = uploadFile(file, type);
                fileUrls.add(fileUrl);
            }
        }
        
        return fileUrls;
    }

    @Override
    public void deleteFile(String fileUrl) {
        try {
            // 从URL中提取文件路径
            String filePath = extractFilePathFromUrl(fileUrl);
            Path file = Paths.get(uploadPath, filePath);
            
            if (Files.exists(file)) {
                Files.delete(file);
                log.info("文件删除成功: {}", fileUrl);
            } else {
                log.warn("文件不存在: {}", fileUrl);
            }
            
        } catch (IOException e) {
            log.error("文件删除失败", e);
            throw new FileUploadException("文件删除失败: " + e.getMessage(), e);
        }
    }

    @Override
    public Object getFileInfo(String fileUrl) {
        try {
            String filePath = extractFilePathFromUrl(fileUrl);
            Path file = Paths.get(uploadPath, filePath);
            
            if (!Files.exists(file)) {
                throw new FileUploadException("文件不存在");
            }
            
            Map<String, Object> fileInfo = new HashMap<>();
            fileInfo.put("url", fileUrl);
            fileInfo.put("size", Files.size(file));
            fileInfo.put("lastModified", Files.getLastModifiedTime(file).toString());
            fileInfo.put("type", Files.probeContentType(file));
            
            return fileInfo;
            
        } catch (IOException e) {
            log.error("获取文件信息失败", e);
            throw new FileUploadException("获取文件信息失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String uploadAvatar(MultipartFile file) {
        return uploadFile(file, "avatar");
    }

    @Override
    public boolean validateFileType(MultipartFile file, String[] allowedTypes) {
        if (file.isEmpty()) {
            return false;
        }
        
        String filename = file.getOriginalFilename();
        if (filename == null) {
            return false;
        }
        
        String extension = getFileExtension(filename).toLowerCase();
        return Arrays.asList(allowedTypes).contains(extension);
    }

    @Override
    public boolean validateFileSize(MultipartFile file, long maxSize) {
        return file.getSize() <= maxSize;
    }

    /**
     * 验证文件
     */
    private void validateFile(MultipartFile file, String type) {
        if (file.isEmpty()) {
            throw new FileUploadException("文件不能为空");
        }
        
        // 验证文件大小
        if (!validateFileSize(file, maxFileSize)) {
            throw new FileUploadException("文件大小不能超过 " + (maxFileSize / 1024 / 1024) + "MB");
        }
        
        // 根据类型验证文件格式
        String[] allowedTypes = getAllowedTypesByCategory(type);
        if (!validateFileType(file, allowedTypes)) {
            throw new FileUploadException("不支持的文件类型，支持的类型: " + Arrays.toString(allowedTypes));
        }
    }

    /**
     * 根据文件类别获取允许的文件类型
     */
    private String[] getAllowedTypesByCategory(String type) {
        switch (type.toLowerCase()) {
            case "avatar":
            case "image":
            case "prescription":
                return IMAGE_TYPES;
            case "document":
            case "report":
                return DOCUMENT_TYPES;
            default:
                return ALL_TYPES;
        }
    }

    /**
     * 获取文件类型目录
     */
    private String getTypeDirectory(String type) {
        switch (type.toLowerCase()) {
            case "avatar":
                return "avatars";
            case "image":
                return "images";
            case "document":
                return "documents";
            case "report":
                return "reports";
            case "prescription":
                return "prescriptions";
            default:
                return "others";
        }
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || filename.lastIndexOf('.') == -1) {
            return "";
        }
        return filename.substring(filename.lastIndexOf('.') + 1);
    }

    /**
     * 生成唯一文件名
     */
    private String generateUniqueFilename() {
        return UUID.randomUUID().toString().replace("-", "") + 
               "_" + System.currentTimeMillis();
    }

    /**
     * 从URL中提取文件路径
     */
    private String extractFilePathFromUrl(String fileUrl) {
        // 移除context path和uploads前缀
        String prefix = "/uploads";
        if (contextPath != null && !contextPath.isEmpty() && !"/".equals(contextPath)) {
            prefix = contextPath + "/uploads";
        }
        
        if (fileUrl.startsWith(prefix)) {
            return fileUrl.substring(prefix.length());
        }
        return fileUrl;
    }
} 